//
//  LocationManager.swift
//  QingLiuSwift
//
//  Created by xyanl on 2024/1/12.
//  Copyright © 2024 考拉🐨. All rights reserved.
//
/**
 是否可以使用定位
 
 即授权未拿到或者未定义plist文件里的授权描述
 info.plist里需要定义的两个key-value信息如下：
 <key>NSLocationAlwaysUsageDescription</key>
 <string>我们将使用你的位置为你提供就近咨询和信息服务</string>
 <key>NSLocationWhenInUseUsageDescription</key>
 <string>我们将使用你的位置为你提供就近咨询和信息服务</string>
 @return YES表示可以使用，NO表示不可以使用，
 */

/**
 CLLocationManager().authorizationStatus
 .notDetermined         用户永不使用地理位置
 .restricted            系统定位服务功能被限制
 .denied                用户禁用地理位置访问服务
 .authorizedAlways      一直使用地理位置
 .authorizedWhenInUse   使用期间使用地理位置
 */

import UIKit
import CoreLocation

protocol LocationManagerDelegate: AnyObject {
    
    /// 授权状态
    func authorizationStatus(_ status: Bool)
    /// 当前定位
    func currentLocation(_ location: CLLocation)
}

@available(iOS 14.0, *)
class LocationManager: NSObject {
    
    lazy var manager: CLLocationManager = {
        let manager = CLLocationManager()
        // 位置管理器代理人是view controller对象.希望view controller 能通过实现 CLLocationManagerDelegate 协议中的方法,获取到当前用户位置信息
        manager.delegate = self
        /// 设置需要的位置精度
        /// kCLLocationAccuracyBestForNavigation ：精度最高，通常用于导航
        /// kCLLocationAccuracyBest ： 精确度最佳
        /// kCLLocationAccuracyNearestTenMeters ：精确度10m之内
        /// kCLLocationAccuracyHundredMeters ：精确度100m之内
        /// kCLLocationAccuracyKilometer ：精确度1000m之内
        /// kCLLocationAccuracyThreeKilometers ：精确度3000m之内
        manager.desiredAccuracy = kCLLocationAccuracyBest
        return manager
    }()
    
    static let shared: LocationManager = LocationManager()
    
    weak var delegate: LocationManagerDelegate?
    
    private var isLocating = false
    
    /// 当前获取到的经纬度
    private(set) var coordinate: CLLocationCoordinate2D?
    
    /// 检查授权状态
    func checkAuthorizationStatus(delegate: LocationManagerDelegate?) {
        self.delegate = delegate
        let status = CLLocationManager().authorizationStatus
        switch status {
        case .notDetermined:
            // 若未确认过授权状态则发起授权请求
            // 使用的时候获取定位信息
            xLog("若未确认过授权状态则发起授权请求")
            CLLocationManager().requestWhenInUseAuthorization()
            
        case .restricted, .denied:
            xLog("无法获取位置信息，请在设置中开启应用程序访问位置信息。")
            delegate?.authorizationStatus(false)
            
        default:
            // 已经有了足够的授权，可以开始更新位置信息
            xLog("已经有了足够的授权，可以开始更新位置信息")
            delegate?.authorizationStatus(true)
        }
    }
    
    /// 判断当前是否可以使用定位
    /// - Returns: （true: 可以定位，false:不可以。, 描述）
    func isCanUseLocation() -> (Bool, String) {
        let status = CLLocationManager().authorizationStatus
        var message = ""
        switch status {
        case .notDetermined:
            message = "用户永不使用地理位置"
            
        case .restricted:
            message = "系统定位服务功能被限制"
            
        case .denied:
            message = "用户禁用地理位置访问服务"
            
        case .authorizedAlways:
            message = "一直使用地理位置"
            
        case .authorizedWhenInUse:
            message = "使用期间使用地理位置"
            
        @unknown default:
            message = ""
            fatalError()
        }
        return (status == .authorizedAlways || status == .authorizedWhenInUse, message)
    }
    
    /// 开始定位
    func startLocation() {
        isLocating = true
        manager.startUpdatingLocation()
    }
    
    /// 停止定位
    func stopLocation() {
        manager.stopUpdatingLocation()
    }
    
}

@available(iOS 14.0, *)
extension LocationManager: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        
        guard let currentLocation = locations.last else { return }
        // 停止定位，
        manager.stopUpdatingLocation()
        
        if !isLocating {
            return
        }
        isLocating = false
        
        xLog("经度 longitude：\(currentLocation.coordinate.longitude)")
        xLog("纬度 latitude：\(currentLocation.coordinate.latitude)")
        
        coordinate = currentLocation.coordinate
        
        delegate?.currentLocation(currentLocation)
    }
    
    func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
        // 当authorizationStatus或accuryauthorization属性发生变化时调用
        // xLog("authorizationStatus 属性发生变化时调用")
        let can = isCanUseLocation().0
        delegate?.authorizationStatus(can)
        
    }
    
}
